#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "cinta.h"

struct celda{
	tuple value;
	aList next;
};

struct sCinta{
	aList pi;
	aList pd;
};

aList aList_vacia(void){
	return NULL;
}

aList aList_destroy(aList lista){
	aList aux = lista;
	assert(lista!=NULL);
	while (aux != NULL){
		lista = aux->next;
		aux->value = tuple_destroy(aux->value);
		free(aux);
		aux = lista;
		}
	return lista;
}

Cinta cinta_create(aList lista){
	Cinta cinta = (Cinta)calloc(1,sizeof(struct sCinta));

	cinta->pi = lista;
	cinta->pd = NULL;
	return cinta;
}

void cinta_arr(Cinta cinta){
	assert(cinta != NULL);
	cinta->pd = cinta->pi;
}

bool cinta_fin(Cinta cinta){
	if (cinta != NULL){
		return cinta->pd == NULL;
		}
	return FALSE;
}

void cinta_av(Cinta cinta){
	assert(!cinta_fin(cinta));
	cinta->pd = cinta->pd->next;
}

tuple cinta_elec(Cinta cinta){
	assert(cinta != NULL);
	assert(!cinta_fin(cinta));
	return cinta->pd->value;
}

void cinta_ins(Cinta cinta, tuple tupla){
	aList rd;
	aList cell = (aList)calloc(1,sizeof(struct celda));
	assert(cinta != NULL);
	cell->value = tuple_clone(tupla);
	if (cinta->pi == NULL){
		cinta->pi = cell;
		cinta->pd = cell;
		cell->next = NULL;
		}
	else{

		/*if((key_le(tuple_fst(tupla),tuple_fst(cinta->pd->value)))){*/
			cinta_arr(cinta);
		/*	}*/
		while (!(key_le(tuple_fst(tupla),tuple_fst(cinta->pd->value))) && (cinta->pd->next != NULL)){
			rd = cinta->pd;
			cinta->pd = cinta->pd->next;
			}


		if (cinta->pd->next == NULL && !key_le(tuple_fst(tupla),tuple_fst(cinta->pd->value))){
			cinta->pd->next = cell;
			cell->next = NULL;
			}

		else if (key_le(tuple_fst(tupla),tuple_fst(cinta->pi->value))){
			 cell->next = cinta->pi;
			 cinta->pi = cell;
			}

		else {
			 cell->next = rd->next;
			 rd->next = cell;
		}
	}
}

void cinta_del(Cinta cinta){
	assert(cinta!=NULL);
	if (cinta->pd == cinta->pi){
		aList tmp = cinta->pi->next;
		cinta->pi->value=tuple_destroy(cinta->pi->value);
		free(cinta->pi);
		cinta->pi = tmp;
		cinta->pd = tmp;
		}
	else {
		aList aux = cinta->pi;
		while (aux->next != cinta->pd){
			aux = aux->next;
		}
		aux->next = cinta->pd->next;
		cinta->pd->value=tuple_destroy(cinta->pd->value);
		free(cinta->pd);
		cinta->pd = aux;
		}
}

aList cinta_destroy(Cinta cinta){
	aList lista = NULL;
	assert(cinta!=NULL);
	lista = cinta->pi;
	free(cinta);
	cinta = NULL;
	return lista;
}
